package cn.com.twoke.application.game.mario.game.entity;

import cn.com.twoke.application.game.mario.core.ecs.world.GameWorld;
import cn.com.twoke.application.game.mario.core.ecs.component.ColliderComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.PositionComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.RigidbodyComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.render.texture.TextureRenderComponent;
import cn.com.twoke.application.game.mario.core.ecs.entity.Entity;
import cn.com.twoke.application.game.mario.game.component.PipeComponent;
import cn.com.twoke.application.game.mario.game.component.TransfersComponent;
import cn.com.twoke.application.game.mario.game.util.PipeUtils;
import cn.com.twoke.application.game.mario.game.config.Tiles;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;

import java.awt.*;
import java.util.function.Consumer;

public class PipeBuilder extends AbstractEntityBuilder<PipeBuilder> {

    private PipeComponent.PipeType pipeType = PipeComponent.PipeType.VERTICAL; // 管道类型
    /**
     * 垂直管道长度
     */
    private Integer verticalLength = 1;
    /**
     * 水平管道长度
     */
    private Integer horizontalLength = 1;
    /**
     * 是否嵌入墙体，暂时在J形状时起作用
     */
    private boolean isEmbeddedWall = false;
    private String textureName = "pipe";
    private Consumer<TransfersComponent.Transfer> addTransferAfterHook = a -> {};

    public PipeBuilder(GameWorld world) {
        super(world);
    }

    public PipeBuilder pipeType(PipeComponent.PipeType pipeType) {
        this.pipeType = pipeType;
        return this;
    }

    public PipeBuilder verticalLength(Integer verticalLength) {
        this.verticalLength = verticalLength;
        return this;
    }

    public PipeBuilder horizontalLength(Integer horizontalLength) {
        this.horizontalLength = horizontalLength;
        return this;
    }

    public PipeBuilder isEmbeddedWall(boolean isEmbeddedWall) {
        this.isEmbeddedWall = isEmbeddedWall;
        return this;
    }

    public PipeBuilder textureName(String textureName) {
        this.textureName = textureName;
        return this;
    }

    public PipeBuilder addTransferAfterHook(Consumer<TransfersComponent.Transfer> addTransferAfterHook) {
        this.addTransferAfterHook = addTransferAfterHook;
        return this;
    }

    @Override
    public Entity build() {
        Entity entity = world.createEntity();
        entity.setType(EntityType.PIPE);
        PositionComponent positionComponent = new PositionComponent(startX, startY);

        PipeComponent pipeComponent = new PipeComponent();
        // 垂直管道长度，默认值为1
        pipeComponent.verticalLength = Opt.ofNullable(verticalLength).orElse(1);
        // 水平管道长度，默认值为1
        pipeComponent.horizontalLength = Opt.ofNullable(horizontalLength).orElse(1);
        pipeComponent.type = Opt.ofNullable(pipeType).orElse(PipeComponent.PipeType.VERTICAL);
        // 是否嵌入墙体
        pipeComponent.isEmbeddedWall = isEmbeddedWall;

        entity.addComponent(positionComponent); // 定位组件
        entity.addComponent(pipeComponent); // 管道组件
        PipeUtils.of(entity, addTransferAfterHook);
        addPipeRigidBody(entity,pipeComponent, world); // 添加管道刚体

        entity.addComponent(TextureRenderComponent.builder()
                .textureId(() -> StrUtil.isBlank(textureName) ? "pipe" : textureName)
                .build());
        // 扩展操作
        Opt.ofNullable(extend).ifPresent(extend ->  extend.accept(entity));
        return entity;
    }


    private void addPipeRigidBody(Entity pipe, PipeComponent pipeComponent, GameWorld world) {
        for (PipeComponent.PipePart pipePart : pipeComponent.pipeParts) {
            Rectangle shape = pipePart.getShape();
            if (pipePart.getType() == PipeComponent.PipePartType.ENTRY_TOP) {
                Entity entity = world.createEntity();
                entity.setParentId(pipe.getId());
                entity.setType(EntityType.RIGID_BODY);
                entity.addComponent(new PositionComponent(shape.x, shape.y));
                entity.addComponent(new ColliderComponent(() -> new Rectangle(shape.x, shape.y, shape.width, shape.height - Tiles.scaleOf(2))));
                RigidbodyComponent rigidbodyComponent = new RigidbodyComponent();
                rigidbodyComponent.bodyType = RigidbodyComponent.BodyType.STATIC;
                entity.addComponent(rigidbodyComponent );
            }
            if (pipePart.getType() == PipeComponent.PipePartType.VERTICAL) {
                Entity entity = world.createEntity();
                entity.setParentId(pipe.getId());
                entity.setType(EntityType.RIGID_BODY);
                int x = shape.x + Tiles.scaleOf(2);
                int y = shape.y;
                int width = shape.width - Tiles.scaleOf(2);
                int height = shape.height;
                if (!pipeComponent.isEmbeddedWall) {
                    y -= Tiles.scaleOf(2);
                    width -= Tiles.scaleOf(3);
                    height += Tiles.scaleOf(2);
                }
                entity.addComponent(new PositionComponent(x, y));
                int finalX = x;
                int finalY = y;
                int finalWidth = width;
                int finalHeight = height;
                entity.addComponent(new ColliderComponent(() -> new Rectangle(finalX, finalY, finalWidth, finalHeight)));
                RigidbodyComponent rigidbodyComponent = new RigidbodyComponent();
                rigidbodyComponent.bodyType = RigidbodyComponent.BodyType.STATIC;
                entity.addComponent(rigidbodyComponent );
            }
            if (pipePart.getType() == PipeComponent.PipePartType.LEFT_JOINT) {
                Entity entity = world.createEntity();
                entity.setParentId(pipe.getId());
                entity.setType(EntityType.RIGID_BODY);
                entity.addComponent(new PositionComponent(shape.x + Tiles.scaleOf(2), shape.y));
                entity.addComponent(new ColliderComponent(() -> new Rectangle(shape.x + Tiles.scaleOf(2), shape.y, shape.width - Tiles.scaleOf(2), shape.height)));
                RigidbodyComponent rigidbodyComponent = new RigidbodyComponent();
                rigidbodyComponent.bodyType = RigidbodyComponent.BodyType.STATIC;
                entity.addComponent(rigidbodyComponent );
            }

            if (pipePart.getType() == PipeComponent.PipePartType.ENTRY_LEFT) {
                Entity entity = world.createEntity();
                entity.setParentId(pipe.getId());
                entity.setType(EntityType.RIGID_BODY);
                entity.addComponent(new PositionComponent(shape.x, shape.y));
                entity.addComponent(new ColliderComponent(() -> new Rectangle(shape.x, shape.y, shape.width - Tiles.scaleOf(2), shape.height)));
                RigidbodyComponent rigidbodyComponent = new RigidbodyComponent();
                rigidbodyComponent.bodyType = RigidbodyComponent.BodyType.STATIC;
                entity.addComponent(rigidbodyComponent );
            }
            if (pipePart.getType() == PipeComponent.PipePartType.HORIZONTAL) {
                Entity entity = world.createEntity();
                entity.setParentId(pipe.getId());
                entity.setType(EntityType.RIGID_BODY);
                int x = shape.x - Tiles.scaleOf(2);
                int y = shape.y + Tiles.scaleOf(2);
                int width = shape.width + Tiles.scaleOf(4);
                int height = shape.height -Tiles.scaleOf(4);
                entity.addComponent(new PositionComponent(x, y));
                entity.addComponent(new ColliderComponent(() -> new Rectangle(x, y, width, height)));
                RigidbodyComponent rigidbodyComponent = new RigidbodyComponent();
                rigidbodyComponent.bodyType = RigidbodyComponent.BodyType.STATIC;
                entity.addComponent(rigidbodyComponent );
            }
        }
    }
}
